package com.ybzl.gateway.netty.handler;


import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.ybzl.gateway.config.Exid;
import com.ybzl.gateway.config.StationConfig;
import com.ybzl.gateway.domain.*;
import com.ybzl.gateway.netty.ChannelGroups;
import com.ybzl.gateway.service.IDeviceService;
import com.ybzl.gateway.utils.SlidingWindowProcessor;
import com.ybzl.gateway.utils.StringToHexUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;

import org.springframework.data.redis.core.RedisTemplate;

import java.net.InetSocketAddress;
import java.util.*;
import java.util.concurrent.ThreadPoolExecutor;

@Slf4j
public class DataHandler extends SimpleChannelInboundHandler<ByteBuf> {

    private IDeviceService deviceService;
    private ThreadPoolExecutor threadPoolExecutor;
    private RedisTemplate redisTemplate;
    private SlidingWindowProcessor slidingWindowProcessor;

    private StationConfig config;

    public DataHandler(IDeviceService deviceService
            , ThreadPoolExecutor threadPoolExecutor
            , RedisTemplate redisTemplate, SlidingWindowProcessor slidingWindowProcessor
            , StationConfig config) {
        this.deviceService = deviceService;
        this.threadPoolExecutor = threadPoolExecutor;
        this.redisTemplate = redisTemplate;
        this.slidingWindowProcessor = slidingWindowProcessor;
        this.config = config;
    }


    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        ChannelGroups.add(ctx.channel());
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        ChannelGroups.discard(ctx.channel());
    }


    @Override
    protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {
        int length = msg.readableBytes();
        byte[] bytes = new byte[length];
        msg.readBytes(bytes);
        StringBuilder hexStr = new StringBuilder();
        for (byte b : bytes) {
            hexStr.append(String.format("%02x", b) + " ");
        }
        log.info("解密后的数据: {}", hexStr);
        String clientIP = ((InetSocketAddress) ctx.channel().remoteAddress()).getAddress().getHostAddress();
        byte cmd = bytes[2];

        switch (cmd) {
            case 0x00:
                // 心跳
                deviceService.insertHeartbeat(new DeviceHeartbeatInfo(clientIP));
                break;
            case 0x01:
                // 电量
                /*threadPoolExecutor.execute(() -> {
                    eleHandler(bytes);
                });*/
                break;
            case 0x03:
                // 能耗
                int energy = StringToHexUtil.twoBytesToIntLittleEndian(Arrays.copyOfRange(bytes, 28, 30));
                int flag = Integer.parseInt(StringToHexUtil.toString(Arrays.copyOfRange(bytes, 30, 32)));
                int power = StringToHexUtil.twoBytesToIntLittleEndian(Arrays.copyOfRange(bytes, 32, 34));
                String id = StringToHexUtil.toString(Arrays.copyOfRange(bytes, 34, 40));
                log.info("能耗值 {} 标志位 {} 电量 {} id {} ", energy, flag, power, id);
                deviceService.saveHighEnergyTag(energy, flag, power, id);
                break;
            case 0x04:
                // 标签
                threadPoolExecutor.execute(() -> {
                    beaconHandler(bytes, clientIP, StringToHexUtil.toString(bytes[2]));
                });
                break;
        }
    }

    /**
     * ibean信息
     *
     * @param bytes
     * @param clientIP
     */
    private void beaconHandler(byte[] bytes, String clientIP, String type) {
        DateTime date = DateUtil.date();
        // 59 42 协议开头
        // 02 类型
        // 27 10 基站id
        // 27 12 标签id
        // c9 标签信号强度rssi
        // 64 标签电量
        // 5a 4c  协议结尾
        String exId = String.format("%04d", Integer.parseInt(StringToHexUtil.toString(Arrays.copyOfRange(bytes, 3, 5)), 16));
        String tagId = String.format("%04d", Integer.parseInt(StringToHexUtil.toString(Arrays.copyOfRange(bytes, 5, 7)), 16));
        int rssi = Integer.valueOf(bytes[7]);
        int tagPower = Integer.valueOf(bytes[8]);
        log.info("基站id {} 标签id {} rssi {} 电量 {}", exId, tagId, rssi, tagPower);
        try {
            Long ts = System.currentTimeMillis();
            deviceService.insertNoIBeacon(ts, exId, tagId, rssi, tagPower);
            //System.out.println("influxdb add result --> " + InfluxClient.write(exId, tagId, rssi, tagPower));
            if (filterData(exId, rssi)) {
                slidingWindowProcessor.addData(new NoIbeacon(ts, exId, tagId, rssi, tagPower, clientIP));
            }
        } catch (Exception e) {
            log.error("{}", e.getMessage(), e);
        }

    }


    private void eleHandler(byte[] bytes) {
        // 59 42 01 27 12 64 5a 4c
        String beaconId = String.format("%04d", Integer.parseInt(StringToHexUtil.toString(Arrays.copyOfRange(bytes, 3, 5)), 16));
        int power = Integer.valueOf(bytes[5]);
        deviceService.insertBeaconStatus(beaconId, power);
    }

    private boolean filterData(String exid,int rssi){
        for (Exid t : config.getExids()){
            if(exid.equals(t.getExId())){
                return  rssi > t.getRssi();
            }
        }
        return false;
    }
}

